1. /* sxmdcvdc.cpp by K.Tsuru */
  2. // function ID = 504 BRADIX (reference)
  3. /*****************************************************************************
  4. SDecimal class
  5. BRADIX ---> DRADIX
  6. Provides the divide radix conversion.
  7. Over 32,000 digits it is faster than ConvertToDec().But for 64,000 digits it
  8. cannot be executed because of the out of memory,then not used in the library.
  9. See
  10. SLong SInteger::DConvToDec() const;
  11. file name : simdcvdc.cpp.
  12. ******************************************************************************/
  13. #ifndef SN_H
  14. #include "sn.h"
  15. #endif
  16. static uint SizeOfSDouble(){
  17. uint sz = sizeof(SDouble);
  18. sz += minArraySize*sizeof(fType);
  19. return sz+8u;
  20. }
  21. SDouble SDecimal::DConvToDec() const{
  22. if(Sign() == 0) return 0.0;
  23. uint N = Last()+1, rsz, z, s;
  24. int d, j, k, q;
  25. d = 16;
  26. rsz = min(N/d, SNMaxSize(REAL));
  27. if(!rsz) rsz++; //divide number rsz >=1; N = rsz*d - g; g >= 0
  28. uint unitsz = SizeOfSDouble();
  29. rsz =ceilpow2(rsz);
  30. while(rsz >= maxSizeOfMemoryBlock/unitsz +1){ // rsz is too large?
  31. d *= 2; rsz /= 2;
  32. }
  33. //evaluate again
  34. rsz = N/d;
  35. if(N % d) rsz++; // rsz > 0
  36. RealSize C;
  37. C.SetEffFig(C.EffFigures()+C.Hidden(), C.TEMP_EXTEND);
  38. SDouble* r = new SDouble[rsz];
  39. //Take into floating point mode for a moment.
  40. r[0].TempPointFree();
  41. SDouble R(1.0/(double)BRADIX), a;
  42. //1/BRADIX can be expressed exactly in double.
  43. // step 1 :It converts into SDouble by d figures independently.
  44. for(k = 0; k < (int)rsz - 1 ; k++){ //pass if rsz == 1
  45. q = (k+1)*d - 1;
  46. r[k].SetInt((int)figure(q)); // Horner's method
  47. for(j = q - 1; j >= k*d; j--){
  48. a.SetInt((int)figure(j));
  49. r[k] = r[k]*R + a; //faster than r[k] = DsDiv(r[k],BRADIX) + a;
  50. }
  51. }
  52. //remaining upper part
  53. k = (int)rsz-1; r[k].SetInt((int)figure(N-1));
  54. for(j = (int)N-2; j >= k*d; j--){
  55. a.SetInt((int)figure(j));
  56. r[k] = r[k]*R + a;
  57. }
  58. r[0].PointModePop(); // r[0].CutDown(POP);
  59. if(rsz == 1) goto Ret;
  60. //step 2 : It converts into SDouble binding two figures of r[].
  61. //It is fast because the FFT multiplication is used.
  62. R.FixedPoint(1);
  63. z = ceilpow2(rsz);
  64. R = Dpow(R, d); // = (1/BRADIX)^d
  65. while(z){
  66. uint i;
  67. for(i = 0; i < z ; i += 2){
  68. if(i+2u <= rsz) r[i/2] = r[i+1]*R + r[i]; //i <= rsz-2
  69. else if(i+1u == rsz) r[i/2] = r[i]; // i == rsz-1
  70. else r[i/2].SetZero(); // i >= rsz
  71. }
  72. z /= 2;
  73. //free disused memory
  74. s = min(2*z, rsz);
  75. for(i = z; i < s; i++) r[i].figure.size(0, 0);
  76. if(z == 1) break; //do not evaluate last R *= R;
  77. R *= R;
  78. }
  79. R.PointFree();
  80. Ret:
  81. //The last result is put in r[0].
  82. C.SetEffFig(0);
  83. R = r[0];
  84. delete[] r;
  85. if( R.Sign() ) R.SetSign(Sign());
  86. R.Reform(504);
  87. return R;
  88. }

sxmdcvdc.cpp : last modifiled at 2017/03/13 14:32:02(2,724 bytes)
created at 2015/12/22 16:09:56
The creation time of this html file is 2017/10/27 15:45:59 (Fri Oct 27 15:45:59 2017).